Emberveil sourcegame/2006Scape Client/src/main/java/ChatCrowns.java
/** Server-assigned chat ranks. Crown tags never come from the message body. */
public final class ChatCrowns {
private ChatCrowns() {}
public static String prefix(int rights) {
return rights >= 1 && rights <= 3 ? "@cr" + rights + "@" : "";
}
public static int rank(String name) {
if(name == null) return 0;
for(int rank=1;rank<=3;rank++) if(name.startsWith(prefix(rank))) return rank;
return 0;
}
public static String strip(String name) {
return rank(name) == 0 ? name : name.substring(5);
}
/** Preserve the original old-school crown silhouette and transparent pixels. */
public static Background owner(StreamLoader archive) {
Background crown = new Background(archive,"mod_icons",1);
for(int i=1;i<crown.anIntArray1451.length;i++) {
int rgb=crown.anIntArray1451[i];
int light=Math.max(rgb>>16&255,Math.max(rgb>>8&255,rgb&255));
// Ember-red body with warm flame highlights; preserve the classic mask.
crown.anIntArray1451[i]=(85+light*170/255)<<16 | light*35/255<<8 | light*45/255;
}
crown.ownerFlame = true;
return crown;
}
public static Background coOwner(StreamLoader archive) {
Background crown = owner(archive);
for (int i=1;i<crown.anIntArray1451.length;i++) crown.anIntArray1451[i]=green(crown.anIntArray1451[i]);
crown.coOwnerFlame=true;
return crown;
}
/** Identity comes from the authenticated chat sender, never message text. */
public static int icon(int rights,String name) {
return rights==3 && "darren".equalsIgnoreCase(strip(name)) ? 3 : Math.max(0,Math.min(2,rights-1));
}
private static int green(int rgb) { return (rgb&0xff) | (rgb>>16&255)<<8 | (rgb>>8&255)<<16; }
private static void flame(Background crown,int x,int y,int rgb,int alpha) {
blend(x,y,crown.coOwnerFlame ? green(rgb) : rgb,alpha);
}
/** Small, bounded flame tongues and a blended red halo, without covering names. */
public static void drawOwner(Background crown, int x, int y, long time) {
int frame = (int)((time / 120L) % 6);
int left = x + crown.anInt1454, top = y + crown.anInt1455;
int w = crown.anInt1452, h = crown.anInt1453;
// Draw the soft halo first. Transparent source pixels stay transparent.
for (int yy=0; yy<h; yy++) for (int xx=0; xx<w; xx++) {
if (crown.aByteArray1450[xx+yy*w] == 0) continue;
flame(crown,left+xx-1,top+yy,0xff1028,55);
flame(crown,left+xx+1,top+yy,0xff1028,55);
flame(crown,left+xx,top+yy-1,0xff1028,65);
flame(crown,left+xx,top+yy+1,0xff1028,45);
}
// Three red fire tongues rise from the crown's points; the tips flicker.
for (int tip=0; tip<3; tip++) {
int xx = tip == 0 ? 1 : tip == 1 ? w/2 : w-2;
int rise = 2 + (frame+tip*2)%3;
for (int yy=0; yy<rise; yy++) {
int sway = yy == rise-1 ? ((frame+tip)%3)-1 : 0;
flame(crown,left+xx+sway,top-yy,yy == 0 ? 0xff7386 : 0xff263e,220-yy*25);
flame(crown,left+xx+sway-1,top-yy,0xff1234,55);
flame(crown,left+xx+sway+1,top-yy,0xff1234,55);
}
}
// Keep the readable classic crown body on top of the glow.
for (int yy=0; yy<h; yy++) for (int xx=0; xx<w; xx++) {
int index = crown.aByteArray1450[xx+yy*w]&255;
if (index != 0) blend(left+xx,top+yy,crown.anIntArray1451[index],256);
}
}
private static void blend(int x, int y, int rgb, int alpha) {
if (x<DrawingArea.topX || x>=DrawingArea.bottomX || y<DrawingArea.topY || y>=DrawingArea.bottomY) return;
int at=x+y*DrawingArea.width, old=DrawingArea.pixels[at], inverse=256-alpha;
DrawingArea.pixels[at]=(((rgb&0xff00ff)*alpha+(old&0xff00ff)*inverse)&0xff00ff00
| ((rgb&0x00ff00)*alpha+(old&0x00ff00)*inverse)&0x00ff0000)>>>8;
}
public static boolean hasOwner(String[] names, String[] messages) {
for (int i=0; i<names.length && i<messages.length; i++)
if (messages[i]!=null && rank(names[i])==3) return true;
return false;
}
}